package com.haoqizhe.kernel.mybatis.generator.plugins;

import com.haoqizhe.kernel.mybatis.generator.utils.AnnotationEnum;
import com.haoqizhe.kernel.mybatis.generator.utils.Constants;
import com.haoqizhe.kernel.mybatis.generator.utils.JavaTypeEnum;
import com.haoqizhe.kernel.mybatis.generator.utils.StringUtils;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * controller控制器 代码生成
 *
 * @author haoqizhe.li
 * @date 2018/4/16 17:14
 */
public class ControllerPlugin extends PluginAdapter {

    private Properties systemPro;

    private FullyQualifiedJavaType controllerType;
    private FullyQualifiedJavaType pojoType;
    private FullyQualifiedJavaType serviceType;
    /**
     * 类文件编码格式
     **/
    private String javaFileEncoding;
    /**
     * model类名
     **/
    private String tableName;
    /**
     * 主键类型
     **/
    private String idJavaType;
    /**
     * 主键JAVA属性名
     */
    private String idJavaProperty;
    /**
     * 表注释
     **/
    private Object tableComment;
    /**
     * service 包名
     **/
    private String servicePackage;
    /**
     * service继承的接口
     **/
    private String serviceInterface;
    /**
     * controller 包名
     **/
    private String targetPackage;
    /**
     * controller 文件夹
     **/
    private String targetProject;
    /**
     * controller 继承的父类
     **/
    private String rootClass;
    /**
     * 是否添加swagger注解
     **/
    private boolean addSwagger;
    /**
     * 生成代码作者
     **/
    private String author;
    /**
     * 是否添加 save 方法
     */
    private boolean addSaveMethod;
    /**
     * 是否添加 update 方法
     */
    private boolean addUpdateMethod;
    /**
     * 是否添加 remove 方法
     */
    private boolean addRemoveMethod;
    /**
     * 是否添加 get 方法
     */
    private boolean addGetMethod;
    /**
     * 是否添加 list 方法
     */
    private boolean addListMethod;
    /**
     * 是否添加 page 方法
     */
    private boolean addPageMethod;
    /**
     * 安全框架，支持 shiro，security 和 空
     */
    private String securityFramework;

    private String resultClass;

    private String pageViewClass;

    private String resultClassName;

    private String pageViewClassName;

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        systemPro = System.getProperties();
        targetPackage = properties.getProperty("targetPackage");
        servicePackage = properties.getProperty("servicePackage");
        serviceInterface = properties.getProperty("serviceInterface");
        targetProject = properties.getProperty("targetProject");
        rootClass = properties.getProperty("rootClass");
        javaFileEncoding = properties.getProperty("javaFileEncoding", "UTF-8");

        author = properties.getProperty("author", systemPro.getProperty("user.name"));

        addSwagger = isTure(properties.getProperty("addSwagger"));

        addSaveMethod = isTure(properties.getProperty("addSaveMethod"));
        addUpdateMethod = isTure(properties.getProperty("addUpdateMethod"));
        addRemoveMethod = isTure(properties.getProperty("addRemoveMethod"));
        addGetMethod = isTure(properties.getProperty("addGetMethod"));
        addListMethod = isTure(properties.getProperty("addListMethod"));
        addPageMethod = isTure(properties.getProperty("addPageMethod"));

        securityFramework = properties.getProperty("securityFramework");
        resultClass = properties.getProperty("resultClass");
        pageViewClass = properties.getProperty("pageViewClass");

        if (servicePackage == null || "".equals(servicePackage)) {
            throw new RuntimeException("ControllerPlugin插件缺少必须的servicePackage参数值");
        }
        if (targetPackage == null || "".equals(targetPackage)) {
            throw new RuntimeException("ControllerPlugin插件缺少必须的targetPackage参数值");
        }
        if (targetProject == null || "".equals(targetProject)) {
            throw new RuntimeException("ControllerPlugin插件缺少必须的targetProject参数值");
        }
        if ((addGetMethod || addRemoveMethod) &&
                (resultClass == null || "".equals(resultClass))) {
            throw new RuntimeException("addGetMethod或者addRemoveMethod为真时，resultClass参数不能为空");
        } else {
            String[] tempArr = resultClass.split("\\.");
            resultClassName = tempArr[tempArr.length - 1];
        }
        if (addPageMethod && (pageViewClass == null || "".equals(pageViewClass))) {
            throw new RuntimeException("addPageMethod为真时，pageQueryClass和pageViewClass参数不能为空");
        } else {
            String[] tempArr2 = pageViewClass.split("\\.");
            pageViewClassName = tempArr2[tempArr2.length - 1];
        }
    }

    protected boolean isTure(String param) {
        boolean check = param == null || "".equals(param) ||
                (!"false".equals(param) && !"true".equals(param));
        return check ? false : Boolean.parseBoolean(param);
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {

        List<GeneratedJavaFile> files = new ArrayList<GeneratedJavaFile>();
        try {
            tableComment = introspectedTable.getRemarks() == null || "".equals(introspectedTable.getRemarks()) ?
                    introspectedTable.getFullyQualifiedTable() : introspectedTable.getRemarks();

            /**
             * 获取实体类名
             */
            String table = introspectedTable.getBaseRecordType();
            String[] names = table.split("\\.");
            tableName = names[names.length - 1];
            /**
             * 获取主键类型
             */
            List<IntrospectedColumn> pkColumn = introspectedTable.getPrimaryKeyColumns();
            idJavaType = pkColumn != null && pkColumn.size() > 0 ?
                    pkColumn.get(0).getFullyQualifiedJavaType().getShortName() : JavaTypeEnum.STRING.code;
            idJavaProperty = pkColumn.get(0).getJavaProperty();
            /**
             * 实体类
             */
            pojoType = new FullyQualifiedJavaType(table);

            controllerType = new FullyQualifiedJavaType(targetPackage +
                    "." + tableName + "Controller");

            serviceType = new FullyQualifiedJavaType(servicePackage +
                    "." + tableName + "Service");

            TopLevelClass topLevelClass = new TopLevelClass(controllerType);

            topLevelClass.addJavaDocLine(StringUtils.getComment(tableComment + "操作接口", author));
            /**
             * 添加注解 和 继承父类
             */
            addImport(topLevelClass);
            /**
             * 添加全局变量
             */
            addField(topLevelClass);
            if (addSaveMethod) {
                topLevelClass.addMethod(getSave(topLevelClass));
            }
            if (addUpdateMethod) {
                topLevelClass.addMethod(getUpdate(topLevelClass));
            }
            if (addRemoveMethod) {
                topLevelClass.addMethod(getRemove(topLevelClass));
            }
            if (addGetMethod) {
                topLevelClass.addMethod(getGet(topLevelClass));
            }
            if (addListMethod) {
                topLevelClass.addMethod(getList(topLevelClass));
            }
            if (addPageMethod) {
                topLevelClass.addMethod(getPage(topLevelClass));
            }

            files.add(addController(topLevelClass));
        } catch (Exception e) {
            throw new RuntimeException("controller插件生成Controller类异常:" + e.getMessage());
        }
        return files;
    }

    /**
     * 添加注解，import必须的类
     *
     * @param topLevelClass controller类
     * @author haoqizhe.li
     * @date 2018/4/17 9:53
     **/
    protected void addImport(TopLevelClass topLevelClass) {
        topLevelClass.addImportedType(pojoType);

        /**
         * 自定义注解
         */
        topLevelClass.addAnnotation(AnnotationEnum.RESPONSE_RESULT.annotation);
        topLevelClass.addImportedType(AnnotationEnum.RESPONSE_RESULT.importedType);

        topLevelClass.addAnnotation(AnnotationEnum.SLF4J.annotation);
        topLevelClass.addImportedType(AnnotationEnum.SLF4J.importedType);

        topLevelClass.addAnnotation(AnnotationEnum.VALIDATED.annotation);
        topLevelClass.addImportedType(AnnotationEnum.VALIDATED.importedType);

        topLevelClass.addAnnotation(AnnotationEnum.REST_CONTROLLER.annotation);
        topLevelClass.addImportedType(AnnotationEnum.REST_CONTROLLER.importedType);

        topLevelClass.addAnnotation(AnnotationEnum.REQUEST_MAPPING.annotation + "(\"/" +
                StringUtils.toLowerCase(tableName) + "\")");
        topLevelClass.addImportedType(AnnotationEnum.REQUEST_MAPPING.importedType);

        /**
         * 添加Swagger接口
         */
        topLevelClass.addAnnotation(AnnotationEnum.API.annotation + "(value = \"" +
                tableComment + "\",tags={\"" + tableComment + "接口\"})");
        topLevelClass.addImportedType(AnnotationEnum.API.importedType);
        /**
         * 继承父类
         */
        topLevelClass.addImportedType(rootClass);
        String[] names = rootClass.split("\\.");
        topLevelClass.setSuperClass(new FullyQualifiedJavaType(names[names.length - 1]));

    }

    /**
     * 添加controller文件
     *
     * @param topLevelClass controller类
     * @author haoqizhe.li
     * @date 2018/4/17 9:53
     **/
    protected GeneratedJavaFile addController(TopLevelClass topLevelClass) {

        topLevelClass.setVisibility(JavaVisibility.PUBLIC);
        return new GeneratedJavaFile(topLevelClass, targetProject, javaFileEncoding, context.getJavaFormatter());
    }

    /**
     * 添加 service 全局变量
     *
     * @param topLevelClass 控制层类
     * @author haoqizhe.li
     * @date 2018/4/16 22:16
     **/
    protected void addField(TopLevelClass topLevelClass) {
        Field field = new Field(StringUtils.toLowerCase(serviceType.getShortName()), serviceType);
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation(AnnotationEnum.AUTOWIRED.annotation);
        topLevelClass.addField(field);
        topLevelClass.addImportedType(serviceType);
        topLevelClass.addImportedType(AnnotationEnum.AUTOWIRED.importedType);
    }


    protected Method getSave(TopLevelClass topLevelClass) {

        Method method = new Method("save");

        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.SAVE_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.SAVE_API_NOTES, tableComment) + "\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
        }

        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.POST_MAPPING.annotation);
        topLevelClass.addImportedType(AnnotationEnum.POST_MAPPING.importedType);

        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.SAVE_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.SAVE_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }
        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);
        /**
         * 方法返回值
         */
        FullyQualifiedJavaType tableJavaType = new FullyQualifiedJavaType(tableName);
        method.setReturnType(tableJavaType);
        /**
         * 方法参数
         */
        Parameter parameter = new Parameter(tableJavaType, "entity", AnnotationEnum.VALIDATED.annotation +
                " " + AnnotationEnum.REQUEST_BODY.annotation);
        topLevelClass.addImportedType(AnnotationEnum.VALIDATED.importedType);
        topLevelClass.addImportedType(AnnotationEnum.REQUEST_BODY.importedType);
        method.addParameter(parameter);
        /**
         * 方法体
         */
        StringBuilder sb = new StringBuilder();
        sb.append(StringUtils.toLowerCase(serviceType.getShortName()) + ".save(entity);");
        sb.append("\n");
        sb.append("        return entity;");
        method.addBodyLine(sb.toString());
        return method;
    }

    protected Method getUpdate(TopLevelClass topLevelClass) {
        Method method = new Method("update");

        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.UPDATE_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.UPDATE_API_NOTES, tableComment) + "\")");
            method.addAnnotation(AnnotationEnum.API_IMPLICIT_PARAM.annotation + "(name = \"id\",value = \"" +
                    Constants.ID_NAME + "\",required = true,dataType = \"" + idJavaType + "\",paramType = \"path\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
            topLevelClass.addImportedType(AnnotationEnum.API_IMPLICIT_PARAM.importedType);
        }
        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.PUT_MAPPING.annotation + "(\"/{id}\")");
        topLevelClass.addImportedType(AnnotationEnum.PUT_MAPPING.importedType);

        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.UPDATE_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.UPDATE_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }
        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);

        /**
         * 方法返回值
         */
        FullyQualifiedJavaType tableJavaType = new FullyQualifiedJavaType(tableName);
        method.setReturnType(tableJavaType);

        /**
         * 方法参数
         */
        String annotation = "";
        if (idJavaType.equals(JavaTypeEnum.STRING.code)) {
            annotation = AnnotationEnum.NotBlank.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotBlank.importedType);
        } else {
            annotation = AnnotationEnum.NotNull.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotNull.importedType);
        }
        FullyQualifiedJavaType idType = new FullyQualifiedJavaType(idJavaType);
        Parameter idParameter = new Parameter(idType, "id",
                AnnotationEnum.PATH_VARIABLE.annotation + " " + annotation + "(message = \"" + Constants.ID_NOT_NULL_MESSAGE + "\")");
        Parameter parameter = new Parameter(tableJavaType, "entity", AnnotationEnum.VALIDATED.annotation +
                " " + AnnotationEnum.REQUEST_BODY.annotation);
        method.addParameter(idParameter);
        method.addParameter(parameter);
        topLevelClass.addImportedType(AnnotationEnum.PATH_VARIABLE.importedType);
        topLevelClass.addImportedType(AnnotationEnum.VALIDATED.importedType);
        topLevelClass.addImportedType(AnnotationEnum.REQUEST_BODY.importedType);

        /**
         * 方法体
         */
        topLevelClass.addImportedType("cn.hutool.core.util.ObjectUtil");
        topLevelClass.addImportedType("com.dgm.kernel.commons.exceptions.DataNotFoundException");
        String tn = StringUtils.toLowerCase(tableName);
        StringBuilder sb = new StringBuilder();
        sb.append(tableName).append(" ").append(tn).append(" = ").append(StringUtils.toLowerCase(serviceType.getShortName())).append(".getById(id);");
        sb.append("\n");
        sb.append("        if(ObjectUtil.isNull(").append(tn).append(")) {");
        sb.append("\n");
        sb.append("            throw new DataNotFoundException();");
        sb.append("\n");
        sb.append("        }").append("\n\n");
        sb.append("        entity.set").append(StringUtils.toUpperCase(idJavaProperty)).append("(id);");
        sb.append("\n");
        sb.append("        ").append(StringUtils.toLowerCase(serviceType.getShortName()) + ".updateById(entity);");
        sb.append("\n");
        sb.append("        return entity;");
        method.addBodyLine(sb.toString());
        return method;
    }

    protected Method getRemove(TopLevelClass topLevelClass) {

        Method method = new Method("delete");
        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.REMOVE_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.REMOVE_API_NOTES, tableComment) + "\")");


            method.addAnnotation(AnnotationEnum.API_RESPONSE.annotation + "(code = 200,message = \"" +
                    Constants.RESULT_MESSAGE_200 + "\",response = " + resultClassName + ".class)");
            method.addAnnotation(AnnotationEnum.API_IMPLICIT_PARAM.annotation + "(name = \"id\",value = \"" +
                    Constants.ID_NAME + "\",required = true,dataType = \"" + idJavaType + "\",paramType = \"path\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
            topLevelClass.addImportedType(AnnotationEnum.API_RESPONSE.importedType);
            topLevelClass.addImportedType(AnnotationEnum.API_IMPLICIT_PARAM.importedType);
            topLevelClass.addImportedType(resultClass);
        }

        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.DELETE_MAPPING.annotation + "(\"/{id}\")");
        topLevelClass.addImportedType(AnnotationEnum.DELETE_MAPPING.importedType);

        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.REMOVE_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.REMOVE_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }
        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);
        /**
         * 方法参数
         */
        String annotation = "";
        if (idJavaType.equals(JavaTypeEnum.STRING.code)) {
            annotation = AnnotationEnum.NotBlank.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotBlank.importedType);
        } else {
            annotation = AnnotationEnum.NotNull.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotNull.importedType);
        }
        FullyQualifiedJavaType idType = new FullyQualifiedJavaType(idJavaType);
        Parameter parameter = new Parameter(idType, "id",
                AnnotationEnum.PATH_VARIABLE.annotation + " " + annotation + "(message = \"" + Constants.ID_NOT_NULL_MESSAGE + "\")");
        topLevelClass.addImportedType(AnnotationEnum.PATH_VARIABLE.importedType);
        method.addParameter(parameter);
        /**
         * 方法体
         */
        topLevelClass.addImportedType("cn.hutool.core.util.ObjectUtil");
        topLevelClass.addImportedType("com.dgm.kernel.commons.exceptions.DataNotFoundException");
        String tn = StringUtils.toLowerCase(tableName);
        StringBuilder sb = new StringBuilder();
        sb.append(tableName).append(" ").append(tn).append(" = ").append(StringUtils.toLowerCase(serviceType.getShortName())).append(".getById(id);");
        sb.append("\n");
        sb.append("        if(ObjectUtil.isNull(").append(tn).append(")) {");
        sb.append("\n");
        sb.append("            throw new DataNotFoundException();");
        sb.append("\n");
        sb.append("        }").append("\n\n");
        sb.append("        ").append(StringUtils.toLowerCase(serviceType.getShortName()) + ".removeById(id);");
        method.addBodyLine(sb.toString());
        return method;
    }

    protected Method getGet(TopLevelClass topLevelClass) {
        Method method = new Method("get");
        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.GET_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.GET_API_NOTES, tableComment) + "\")");

            method.addAnnotation(AnnotationEnum.API_IMPLICIT_PARAM.annotation + "(name = \"id\",value = \"" +
                    Constants.ID_NAME + "\",required = true,dataType = \"" + idJavaType + "\",paramType = \"path\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
            topLevelClass.addImportedType(AnnotationEnum.API_RESPONSE.importedType);
            topLevelClass.addImportedType(AnnotationEnum.API_IMPLICIT_PARAM.importedType);
            topLevelClass.addImportedType(resultClass);
        }
        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.GET_MAPPING.annotation + "(\"/{id}\")");
        topLevelClass.addImportedType(AnnotationEnum.GET_MAPPING.importedType);
        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.GET_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.GET_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }

        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);

        /**
         * 方法返回值
         */
        FullyQualifiedJavaType tableJavaType = new FullyQualifiedJavaType(tableName);
        method.setReturnType(tableJavaType);

        /**
         * 方法参数
         */
        String annotation = "";
        if (idJavaType.equals(JavaTypeEnum.STRING.code)) {
            annotation = AnnotationEnum.NotBlank.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotBlank.importedType);
        } else {
            annotation = AnnotationEnum.NotNull.annotation;
            topLevelClass.addImportedType(AnnotationEnum.NotNull.importedType);
        }
        FullyQualifiedJavaType idType = new FullyQualifiedJavaType(idJavaType);
        Parameter parameter = new Parameter(idType, "id",
                AnnotationEnum.PATH_VARIABLE.annotation + " " + annotation + "(message = \"" + Constants.ID_NOT_NULL_MESSAGE + "\")");
        topLevelClass.addImportedType(AnnotationEnum.PATH_VARIABLE.importedType);
        method.addParameter(parameter);

        /**
         * 方法体
         */
        topLevelClass.addImportedType("cn.hutool.core.util.ObjectUtil");
        topLevelClass.addImportedType("com.dgm.kernel.commons.exceptions.DataNotFoundException");
        String tn = StringUtils.toLowerCase(tableName);

        StringBuilder sb = new StringBuilder();
        sb.append(tableName).append(" ").append(tn).append(" = ").append(StringUtils.toLowerCase(serviceType.getShortName())).append(".getById(id);");
        sb.append("\n");
        sb.append("        if(ObjectUtil.isNull(").append(tn).append(")) {");
        sb.append("\n");
        sb.append("            throw new DataNotFoundException();");
        sb.append("\n");
        sb.append("        }").append("\n");
        sb.append("        return ").append(tn).append(";");
        method.addBodyLine(sb.toString());
        return method;
    }

    protected Method getList(TopLevelClass topLevelClass) {
        topLevelClass.addImportedType("java.util.List");

        Method method = new Method("list");
        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.LIST_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.LIST_API_NOTES, tableComment) + "\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
        }
        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.GET_MAPPING.annotation + "(\"" + Constants.LIST_API_PATH + "\")");
        topLevelClass.addImportedType(AnnotationEnum.GET_MAPPING.importedType);
        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.LIST_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.LIST_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }
        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);
        /**
         * 方法返回值
         */
        FullyQualifiedJavaType tableJavaType = new FullyQualifiedJavaType("List<" + tableName + ">");
        method.setReturnType(tableJavaType);

        /**
         * 方法体
         */
        StringBuilder sb = new StringBuilder();
        sb.append(" return " + StringUtils.toLowerCase(serviceType.getShortName()) + ".list(getWrapper());");
        method.addBodyLine(sb.toString());
        return method;
    }

    protected Method getPage(TopLevelClass topLevelClass) {
        topLevelClass.addImportedType(pageViewClass);

        Method method = new Method("page");
        if (addSwagger) {
            /**
             * 添加 swagger 注解
             */
            method.addAnnotation(AnnotationEnum.API_OPERATION.annotation + "(value = \"" +
                    String.format(Constants.PAGE_API_VALUE, tableComment) + "\",notes = \"" +
                    String.format(Constants.PAGE_API_NOTES, tableComment) + "\")");
            topLevelClass.addImportedType(AnnotationEnum.API_OPERATION.importedType);
        }
        /**
         * 添加Request Mapping 注解
         */
        method.addAnnotation(AnnotationEnum.GET_MAPPING.annotation + "(\"" + Constants.PAGE_API_PATH + "\")");
        topLevelClass.addImportedType(AnnotationEnum.GET_MAPPING.importedType);
        /**
         * shiro权限框架
         */
        if (Constants.SECURITY_FRAMEWORK_SHIRO.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.REQUIRES_PERMISSIONS.annotation +
                    "(\"" + tableName.toLowerCase() + Constants.PAGE_API_SHIRO_KEY + "\")");
            topLevelClass.addImportedType(AnnotationEnum.REQUIRES_PERMISSIONS.importedType);
        } else if (Constants.SECURITY_FRAMEWORK_SECURITY.equals(securityFramework)) {
            method.addAnnotation(AnnotationEnum.PRE_AUTHORIZE.annotation + "(\"hasAnyRole('" +
                    tableName.toUpperCase() + Constants.PAGE_API_SECURITY_KEY + "')\")");
            topLevelClass.addImportedType(AnnotationEnum.PRE_AUTHORIZE.importedType);
        }
        /**
         * 方法修饰符 设置为 public
         */
        method.setVisibility(JavaVisibility.PUBLIC);
        /**
         * 方法返回值
         */
        FullyQualifiedJavaType tableJavaType = new FullyQualifiedJavaType(pageViewClassName + "<" + tableName + ">");
        method.setReturnType(tableJavaType);

        /**
         * 方法体
         */
        StringBuilder sb = new StringBuilder();
        sb.append(" return pageBuild(" + StringUtils.toLowerCase(serviceType.getShortName()) + ".page(getPage(), getWrapper()));");
        method.addBodyLine(sb.toString());

        return method;
    }
}
